use crate::common::{Server, UpdateInfo};
use clap::ArgAction::Version;
use rstest::{fixture, rstest};
use share::core::channel::Channel;
use share::core::device_id::DeviceId;
use share::core::native_version::NativeVersion;
use std::{str::FromStr, sync::Arc};
use tokio::sync::Mutex;

mod common;

#[fixture]
async fn shared_server() -> Arc<Mutex<Server>> {
    common::shared_server().await
}

/// 测试获取更新信息的API接口
///
/// 这个测试验证本地服务器和生产环境服务器的 `/update_info` 接口返回结果是否一致。
/// 测试会针对不同的渠道(channel)和版本号(version)组合进行验证，确保:
/// 1. 本地服务器的实现与生产环境行为一致
/// 2. 接口能正确处理不同渠道和版本的请求
/// 3. 返回的更新信息数据结构正确
///
/// 测试步骤:
/// 1. 向本地测试服务器发送带参数的请求
/// 2. 向生产环境服务器发送相同的请求
/// 3. 比较两个返回结果是否完全一致
///
/// 测试用例覆盖所有的外网上线的所有渠道
#[tokio::test]
#[rstest]
#[case("QooApp", 40)]
#[case("GooglePlay", 56)]
#[case("AppStore", 799)]
#[case("TapTapMainland", 3)]
#[case("BiliBiliMainland", 3)]
#[case("AppStoreMainland", 599)]
async fn test_get_update_info(
    #[future] shared_server: Arc<Mutex<Server>>,
    #[case] channel: String,
    #[case] version: u32,
) {
    let channel = Channel::from_str(&channel).unwrap();
    let shared_server = shared_server.await;

    let result = shared_server
        .lock()
        .await
        .get(format!("/update_info?channel={channel}&version={version}"))
        .await;
    let update_info: UpdateInfo = serde_json::from_str(&result).unwrap();

    let url = format!(
        "https://{}/update_info?channel={channel}&version={version}",
        channel.get_api_domain()
    );
    let result_remote = reqwest::get(url)
        .await
        .unwrap()
        .error_for_status()
        .unwrap()
        .text()
        .await
        .unwrap();
    let expected_update_info: UpdateInfo = serde_json::from_str(&result_remote).unwrap();

    assert_eq!(update_info, expected_update_info);
}

/// 测试使用未知的母包版本号去获取更新信息
///
/// 当母包版本号没有被包含在设置中时，需要正常返回UpdateInfo信息，在这种情况下，返回的资源版本号和资源链接为空(不能是空字符串)
///
/// 测试步骤：
/// 1.获取渠道信息
/// 2.使用未知母包版本号获取更新信息
/// 3.比较更新信息和渠道信息中的对应内容
///
/// 测试用例覆盖线上所有渠道
#[tokio::test]
#[rstest]
#[case("QooApp", 0)]
#[case("QooApp", 1)]
#[case("GooglePlay", 0)]
#[case("GooglePlay", 1)]
#[case("AppStore", 0)]
#[case("AppStore", 1)]
#[case("TapTapMainland", 0)]
#[case("TapTapMainland", 1)]
#[case("BiliBiliMainland", 0)]
#[case("BiliBiliMainland", 1)]
#[case("AppStoreMainland", 0)]
#[case("AppStoreMainland", 1)]
async fn test_native_version_not_include_should_success(
    #[future] shared_server: Arc<Mutex<Server>>,
    #[case] channel: String,
    #[case] version: u32,
) {
    let channel = Channel::from_str(&channel).unwrap();
    let shared_server = shared_server.await;
    let version = NativeVersion::new(version).unwrap();

    let server_guard = shared_server.lock().await;
    let channel_info = server_guard.fetch_channel_info(channel).await;
    let update_info = server_guard
        .fetch_update_info(channel, version, DeviceId::default())
        .await;

    assert_eq!(update_info.channel, channel_info.name);
    assert_eq!(
        update_info.min_native_version,
        channel_info.min_native_version
    );
    assert_eq!(
        update_info.latest_native_version,
        channel_info.latest_native_version
    );
    assert_eq!(update_info.jump_url, channel_info.jump_url);
    assert_eq!(update_info.raw_resource_version, None);
    assert_eq!(update_info.default_resource_version, None);
    assert_eq!(update_info.resource_url, None);
}
